package com.erebus.service.impl;

import com.erebus.model.dto.User;
import com.erebus.model.dto.UserDto;
import com.erebus.service.EightCharactersService;
import com.erebus.utils.Pregnancy;
import com.nlf.calendar.Solar;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


@Service
public class EightCharactersServiceImpl implements EightCharactersService {

    @Autowired
    RedisTemplate redisTemplate;

    // 阳历转阴历
    @Override
    public String getEightCharacters(String redisKey) {

        User user = (User) redisTemplate.opsForValue().get(redisKey);

        String eightCharacters = Pregnancy.getEightCharacters(user.getYear(), user.getMonth(), user.getDay(), user.getHour(), user.getMinute());


        return eightCharacters;
    }

    // 起运时间
    @Override
    public String qiyun(String redisKey) {
        User user = (User) redisTemplate.opsForValue().get(redisKey);

        // 计算生日的前后两个节气
        Solar[] solars = Pregnancy.getSolarTerm(user.getYear(), user.getMonth(), user.getDay(), user.getHour(), user.getMinute());
        int num = Pregnancy.qiyun(user.getYear(), user.getMonth(), user.getDay(), user.getHour(), user.getMinute(), solars, user.getSex());
        int[] qiyun = Pregnancy.convertMinutesToTime(num);

        user.setNum(num);
        redisTemplate.delete(redisKey);
        redisTemplate.opsForValue().set(redisKey, user);
        return qiyun[0] + "年" + qiyun[1] + "月" + qiyun[2] + "日" + qiyun[3] + "时";
    }

    @Override
    public String jiaoyun(String redisKey) {
        User user = (User) redisTemplate.opsForValue().get(redisKey);
        int[] ints = Pregnancy.obscurity3(user.getYear(), user.getMonth(), user.getDay(), user.getHour(), user.getMinute(), user.getNum());
        return ints[0] + "年" + ints[1] + "月" + ints[2] + "日" + ints[3] + "时";
    }

    @Override
    public UserDto paipan(String redisKey) {
        User user = (User) redisTemplate.opsForValue().get(redisKey);
        UserDto userDto = new UserDto();

        // 1,农历
        String eightCharacters = Pregnancy.getEightCharacters(user.getYear(), user.getMonth(), user.getDay(), user.getHour(), user.getMinute());
        user.setEightCharacters(eightCharacters);
        String[] sizhu = user.getSizhu();
        sizhu[0] = eightCharacters.substring(0, 1);
        sizhu[1] = eightCharacters.substring(1, 2);
        sizhu[2] = eightCharacters.substring(3, 4);
        sizhu[3] = eightCharacters.substring(4, 5);
        sizhu[4] = eightCharacters.substring(6, 7);
        sizhu[5] = eightCharacters.substring(7, 8);
        sizhu[6] = eightCharacters.substring(9, 10);
        sizhu[7] = eightCharacters.substring(10, 11);
        user.setSizhu(sizhu);
        // 庚辰年癸未月甲戌日甲戌时

        // 2，起运
        Solar[] solars = Pregnancy.getSolarTerm(user.getYear(), user.getMonth(), user.getDay(), user.getHour(), user.getMinute());
        int num = Pregnancy.qiyun(user.getYear(), user.getMonth(), user.getDay(), user.getHour(), user.getMinute(), solars, user.getSex());
        int[] qiyun = Pregnancy.convertMinutesToTime(num);
        user.setNum(num);
        String temp = qiyun[0] + "年" + qiyun[1] + "月" + qiyun[2] + "日" + qiyun[3] + "时";
        user.setQiyun(qiyun);

        // 3，交运
        int[] ints = Pregnancy.obscurity3(user.getYear(), user.getMonth(), user.getDay(), user.getHour(), user.getMinute(), user.getNum());
        String temp1 = ints[0] + "年" + ints[1] + "月" + ints[2] + "日" + ints[3] + "时";

        // 4,十神
        String bazi = user.getEightCharacters();
        sizhu = user.getSizhu();
        String rigan = sizhu[4];
        String shishen1 = shishen(rigan, sizhu[0]); // 年
        String shishen2 = shishen(rigan, sizhu[2]); // 月
        String shishen3 = shishen(rigan, sizhu[6]); // 时
        String[] tianGods = user.getTianGods();
        tianGods[0] = shishen1;
        tianGods[1] = shishen2;
        tianGods[2] = "日主";
        tianGods[3] = shishen3;
        user.setTianGods(tianGods);

        // 地支藏气
        sizhu = user.getSizhu();
        String[] nianqi = dizhiCangqi(sizhu[1]); // 年支藏气
        String[] yueqi = dizhiCangqi(sizhu[3]);// 月支藏气
        String[] riqi = dizhiCangqi(sizhu[5]);// 日支藏气
        String[] shiqi = dizhiCangqi(sizhu[7]);// 时支藏气
        String[][] dizhizangqi = user.getDizhizangqi();
        dizhizangqi[0] = nianqi;
        dizhizangqi[1] = yueqi;
        dizhizangqi[2] = riqi;
        dizhizangqi[3] = shiqi;
        user.setDizhizangqi(dizhizangqi);
        // 地支十神
        String[][] dizhishishen = user.getDizhishishen();
        for (int i = 0; i < nianqi.length; i++) {
            dizhishishen[0][i] = shishen(rigan, nianqi[i]);
        }
        for (int i = 0; i < yueqi.length; i++) {
            dizhishishen[1][i] = shishen(rigan, yueqi[i]);
        }
        for (int i = 0; i < riqi.length; i++) {
            dizhishishen[2][i] = shishen(rigan, riqi[i]);
        }
        for (int i = 0; i < shiqi.length; i++) {
            dizhishishen[3][i] = shishen(rigan, shiqi[i]);
        }
        user.setDizhishishen(dizhishishen);

        // 旺衰
        String wangshuai1 = Pregnancy.wangshuai(user.getSizhu()[4], user.getSizhu()[1]);
        String wangshuai2 = Pregnancy.wangshuai(user.getSizhu()[4], user.getSizhu()[3]);
        String wangshuai3 = Pregnancy.wangshuai(user.getSizhu()[4], user.getSizhu()[5]);
        String wangshuai4 = Pregnancy.wangshuai(user.getSizhu()[4], user.getSizhu()[7]);
        String[] wangshuai = new String[]{wangshuai1, wangshuai2, wangshuai3, wangshuai4};
        user.setWangshuai(wangshuai);

        // 纳音
        String nayin1 = Pregnancy.nayin(user.getSizhu()[0], user.getSizhu()[1]);
        String nayin2 = Pregnancy.nayin(user.getSizhu()[2], user.getSizhu()[3]);
        String nayin3 = Pregnancy.nayin(user.getSizhu()[4], user.getSizhu()[5]);
        String nayin4 = Pregnancy.nayin(user.getSizhu()[6], user.getSizhu()[7]);
        String[] nayin = new String[]{nayin1, nayin2, nayin3, nayin4};
        user.setNayin(nayin);



        redisTemplate.delete(redisKey);
        redisTemplate.opsForValue().set(redisKey, user);
        userDto.setYinli(eightCharacters);
        userDto.setQiyun(temp);
        userDto.setJiaoyun(temp1);
        userDto.setTianGods(user.getTianGods());
        userDto.setDizhizangqi(user.getDizhizangqi());
        userDto.setDizhishishen(user.getDizhishishen());
        userDto.setWangshuai(user.getWangshuai());
        userDto.setNayin(user.getNayin());


        return userDto;
    }

    // 地支藏气
    private String[] dizhiCangqi(String dizhi) {
        return switch (dizhi) {
            case "子" -> new String[]{"癸"};
            case "丑" -> new String[]{"己", "癸", "戊"};
            case "寅" -> new String[]{"甲", "丙", "戊"};
            case "卯" -> new String[]{"乙"};
            case "辰" -> new String[]{"戊", "乙", "癸"};
            case "巳" -> new String[]{"丙", "庚", "戊"};
            case "午" -> new String[]{"丁", "己"};
            case "未" -> new String[]{"己", "丁", "乙"};
            case "申" -> new String[]{"庚", "壬", "戊"};
            case "酉" -> new String[]{"辛"};
            case "戌" -> new String[]{"戊", "辛", "丁"};
            case "亥" -> new String[]{"壬", "甲"};
            default -> new String[]{""};
        };

    }

    // 十神/

    /**
     * rigen   丁
     * x 要算的干支
     *
     * @return 偏印
     */
    private String shishen(String rigen, String x) {

        // 1 日干对应的阴阳
        String riYinYang = ganzhiToyinyang(rigen);
        // 2 日干对应的五行
        String riWuXing = ganzhiTowuxing(rigen);

        String xyingYang = ganzhiToyinyang(x);
        String xWuXing = ganzhiTowuxing(x);

        // 同性 比食偏
        if (riYinYang.equals(xyingYang)) {
            if (riWuXing.equals("木")) {
                return switch (xWuXing) {
                    case "水" -> "偏印";
                    case "木" -> "比肩";
                    case "火" -> "食神";
                    case "土" -> "偏财";
                    case "金" -> "偏官";
                    default -> throw new IllegalStateException("Unexpected value: " + xWuXing);
                };
            }

            if (riWuXing.equals("火")) {
                return switch (xWuXing) {
                    case "水" -> "偏官";
                    case "木" -> "偏印";
                    case "火" -> "比肩";
                    case "土" -> "食神";
                    case "金" -> "偏财";
                    default -> throw new IllegalStateException("Unexpected value: " + xWuXing);
                };
            }
            if (riWuXing.equals("土")) {
                return switch (xWuXing) {
                    case "水" -> "偏财";
                    case "木" -> "偏官";
                    case "火" -> "偏印";
                    case "土" -> "比肩";
                    case "金" -> "食神";
                    default -> throw new IllegalStateException("Unexpected value: " + xWuXing);
                };
            }
            if (riWuXing.equals("金")) {
                return switch (xWuXing) {
                    case "水" -> "食神";
                    case "木" -> "偏财";
                    case "火" -> "偏官";
                    case "土" -> "偏印";
                    case "金" -> "比肩";
                    default -> throw new IllegalStateException("Unexpected value: " + xWuXing);
                };
            }
            if (riWuXing.equals("水")) {
                return switch (xWuXing) {
                    case "水" -> "比肩";
                    case "木" -> "食神";
                    case "火" -> "偏财";
                    case "土" -> "偏官";
                    case "金" -> "偏印";
                    default -> throw new IllegalStateException("Unexpected value: " + xWuXing);
                };
            }
        } else {

            if (riWuXing.equals("木")) {
                return switch (xWuXing) {
                    case "水" -> "正印";
                    case "木" -> "劫财";
                    case "火" -> "伤官";
                    case "土" -> "正财";
                    case "金" -> "正官";
                    default -> throw new IllegalStateException("Unexpected value: " + xWuXing);
                };
            }

            if (riWuXing.equals("火")) {
                return switch (xWuXing) {
                    case "水" -> "正官";
                    case "木" -> "正印";
                    case "火" -> "劫财";
                    case "土" -> "伤官";
                    case "金" -> "正财";
                    default -> throw new IllegalStateException("Unexpected value: " + xWuXing);
                };
            }
            if (riWuXing.equals("土")) {
                return switch (xWuXing) {
                    case "水" -> "正财";
                    case "木" -> "正官";
                    case "火" -> "正印";
                    case "土" -> "劫财";
                    case "金" -> "伤官";
                    default -> throw new IllegalStateException("Unexpected value: " + xWuXing);
                };
            }
            if (riWuXing.equals("金")) {
                return switch (xWuXing) {
                    case "水" -> "伤官";
                    case "木" -> "正财";
                    case "火" -> "正官";
                    case "土" -> "正印";
                    case "金" -> "劫财";
                    default -> throw new IllegalStateException("Unexpected value: " + xWuXing);
                };
            }
            if (riWuXing.equals("水")) {
                return switch (xWuXing) {
                    case "水" -> "劫财";
                    case "木" -> "伤官";
                    case "火" -> "正财";
                    case "土" -> "正官";
                    case "金" -> "正印";
                    default -> throw new IllegalStateException("Unexpected value: " + xWuXing);
                };
            }
        }

        return "错误";
    }

    // 传入天干地支，返回阴阳
    private String ganzhiToyinyang(String ganzhi) {

        return switch (ganzhi) {
            case "甲", "丙", "戊", "庚", "壬", "子", "寅", "辰", "午", "申", "戌" -> "阳";
            case "乙", "丁", "己", "辛", "癸", "丑", "卯", "巳", "未", "酉", "亥" -> "阴";
            default -> "未知";
        };

    }

    private String ganzhiTowuxing(String ganzhi) {

        return switch (ganzhi) {
            case "甲", "乙", "寅", "卯" -> "木";
            case "丙", "丁", "巳", "午" -> "火";
            case "戊", "己", "辰", "戌", "丑", "未" -> "土";
            case "庚", "辛", "申", "酉" -> "金";
            case "壬", "癸", "亥", "子" -> "水";
            default -> "未知";
        };
    }

}
